package com.wn.icloud.auth.service.impl;

import com.wn.icloud.auth.entity.AppVersionManage;
import com.wn.icloud.auth.mapper.AppVersionManageDao;
import com.wn.icloud.auth.service.AuthService;
import com.wn.icloud.common.msg.ObjectRestCode;
import com.wn.icloud.common.msg.ObjectRestResponse;
import com.wn.icloud.common.util.user.JwtAuthenticationRequest;
import com.wn.icloud.auth.util.user.JwtTokenUtil;
import com.wn.icloud.common.utils.UUIDUtil;
import com.wn.icloud.common.vo.user.UserInfo;
import com.wn.icloud.common.exception.auth.UserInvalidException;
import com.wn.icloud.common.util.jwt.JWTInfo;
import com.wn.icloud.provider.uac.remote.UserFeignApi;
import com.wn.icloud.provider.uac.remote.constant.UserRedisKeyConstant;
import com.wn.icloud.provider.uac.remote.vo.LoginReqVO;
import com.wn.icloud.provider.uac.remote.vo.ResetUserPassWordReqVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private UserFeignApi userFeignApi;

    @Autowired
    private AppVersionManageDao appVersionManageDao;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Value("${user.password-reset-time}")
    private Long passwordResetTime;

    @Value("${user.login.type-password.time}")
    private Long limitPassWordTime;
    @Value("${user.login.type-password.limit}")
    private Integer limitPassWord;
    @Value("${user.login.type-code.time}")
    private Long limitCodeTime;
    @Value("${user.login.type-code.time}")
    private Integer limitCode;


    @Override
    public ObjectRestResponse login(LoginReqVO loginReqVO) throws Exception {
        UserInfo info = userFeignApi.login(loginReqVO);
        if (!StringUtils.isEmpty(info.getId())) {
            return ObjectRestResponse.success(jwtTokenUtil.generateToken(new JWTInfo(info.getUsername(), info.getId() + "", info.getName())));
        }
        String limitKey = UserRedisKeyConstant.LOGIN_TYPE_PASSWORD + loginReqVO.getMobilePhone();
        Object limitValue = redisTemplate.opsForValue().get(limitKey);
        if (StringUtils.isEmpty(limitValue)){
            redisTemplate.opsForValue().set(limitKey,0 );
            //todo 需要设置一个较大的值
        }else {
            int limitNumber = (int) redisTemplate.opsForValue().get(limitKey);
            if ((limitPassWord-1) == limitNumber){
                redisTemplate.expire(limitKey, limitPassWordTime, TimeUnit.MILLISECONDS);
                return ObjectRestResponse.failure(ObjectRestCode.FAILURE_LIMIT);
            }
            redisTemplate.opsForValue().increment(limitKey,1);

        }
        return ObjectRestResponse.failure(ObjectRestCode.USER_LOGIN_ERROR);
    }

    @Override
    public ObjectRestResponse loginPhone(LoginReqVO loginReqVO) throws Exception {
        UserInfo info = userFeignApi.loginPhone(loginReqVO);
        if (!StringUtils.isEmpty(info.getId())) {
            return ObjectRestResponse.success(jwtTokenUtil.generateToken(new JWTInfo(info.getUsername(), info.getId() + "", info.getName())));
        }
        String limitKey = UserRedisKeyConstant.LOGIN_TYPE_CODE + loginReqVO.getMobilePhone();
        Object limitValue = redisTemplate.opsForValue().get(limitKey);
        if (StringUtils.isEmpty(limitValue)){
            redisTemplate.opsForValue().set(limitKey,0 );
            //todo 需要设置一个较大的值
        }else {
            int limitNumber = (int) redisTemplate.opsForValue().get(limitKey);
            if ((limitCode -1)== limitNumber){
                redisTemplate.expire(limitKey, limitCodeTime, TimeUnit.MILLISECONDS);
                return ObjectRestResponse.failure(ObjectRestCode.FAILURE_LIMIT);
            }
            redisTemplate.opsForValue().increment(limitKey,1);
        }
        return ObjectRestResponse.failure(ObjectRestCode.USER_LOGIN_CODE_ERROR);
    }

    @Override
    public void validate(String token) throws Exception {
        jwtTokenUtil.getInfoFromToken(token);
    }

    @Override
    public String genTestToken(String userName, String userId) throws Exception {
        return jwtTokenUtil.generateToken(new JWTInfo(userName, userId, userName));
    }

    /**
     * 重置密码获取凭证密钥
     * @param
     * @return
     */
    @Override
    public ObjectRestResponse resetPassCode(ResetUserPassWordReqVO resetUserPassWordReqVO) {
        Object realCodeValue = redisTemplate.opsForValue().get(UserRedisKeyConstant.RESET_PASSWORD + resetUserPassWordReqVO.getPhone());
        if (StringUtils.isEmpty(realCodeValue)){
            return ObjectRestResponse.failure(ObjectRestCode.SMS_OVER);
        }
        if (!realCodeValue.toString().equals(resetUserPassWordReqVO.getCode())){
            return ObjectRestResponse.failure(ObjectRestCode.SMS_ERROR);
        }
        String redisKey = UserRedisKeyConstant.PASSWORD_RESET_KEY + resetUserPassWordReqVO.getPhone();
        String uid  = UUIDUtil.getUUID();
        redisTemplate.opsForValue().set(redisKey, uid);
        redisTemplate.expire(redisKey, passwordResetTime, TimeUnit.MILLISECONDS);
        return ObjectRestResponse.success(uid);
    }

    /**
     * 重置用户密码
     * @param resetUserPassWordReqVO
     * @return
     */
    @Override
    public ObjectRestResponse resetUserPassWord(ResetUserPassWordReqVO resetUserPassWordReqVO) {
        return userFeignApi.resetUserPassWord(resetUserPassWordReqVO);
    }



    @Override
    public String refresh(String oldToken) throws Exception {
        return jwtTokenUtil.generateToken(jwtTokenUtil.getInfoFromToken(oldToken));
    }

    /**
     * 获取版本信息
     */
    @Override
    public ObjectRestResponse versionInfo(String version) {
        AppVersionManage appVersionManage = appVersionManageDao.queryByVersion(version);
        return ObjectRestResponse.success(appVersionManage);
    }
}
